﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Newtonsoft.Json;
using System.Threading;
using System.Diagnostics;
using EntityDesigner2.Extensions;
using EntityDesigner2.Controls;

namespace EntityDesigner2
{
    public partial class FrmMain : Form
    {
        // 私有变量
        private string _localPath;
        private string _localConfigPath;
        private string _exePath;
        private string _path;
        private string _pathData;
        private Table _table;
        private Configs.Setting _setting;
        private Configs.Data _data;
        private bool _editControlWorking;
        private EdListBox _editListBox;
        private string _editValue;

        // 初始化地址
        public string InitPath { get; set; }

        public FrmMain()
        {
            InitializeComponent();
        }

        #region [=====通用方法=====]

        // 设置状态
        private void SetStatus(string content, int wait = 10)
        {
            this.toolStripStatusLabel1.Text = content;
            Application.DoEvents();
            Thread.Sleep(wait);
        }

        // 获取整型数据
        private int ParseInt(object value, int defaultValue = 0)
        {
            if (value is int) return (int)value;
            if (int.TryParse(value.ToString(), out int res))
            {
                return res;
            }
            return defaultValue;
        }

        // 获取整型数据
        private string ParseString(object value, string defaultValue = "")
        {
            if (value is null) return defaultValue;
            if (value is string) return ((string)value).Trim();
            return value.ToString().Trim();
        }

        // 获取整型数据
        private bool ParseBoolean(object value, bool defaultValue = false)
        {
            if (value is null) return defaultValue;
            if (value is bool) return (bool)value;
            return ParseString(value).ToLower() == "true";
        }

        // 获取下划线命名法
        private string GetUnderScoreCase(string str)
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < str.Length; i++)
            {
                char chr = str[i];
                if (chr >= 'A' && chr <= 'Z')
                {
                    if (i == 0)
                    {
                        sb.Append(chr.ToString().ToLower());
                    }
                    else
                    {
                        sb.Append('_');
                        sb.Append(chr.ToString().ToLower());
                    }
                }
                else
                {
                    sb.Append(chr);
                }
            }
            return sb.ToString();
        }

        // 获取下划线命名法
        private string GetAbbr(string str)
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < str.Length; i++)
            {
                char chr = str[i];
                if (chr >= 'A' && chr <= 'Z')
                {
                    sb.Append(chr.ToString().ToLower());
                }
            }
            return sb.ToString();
        }

        // 获取空格字符串
        private string Space(int len)
        {
            return new string(' ', len);
        }

        #endregion

        #region [=====显示相关=====]

        // 显示字段
        private void ShowColumns()
        {
            var view = this.dataGridView1;
            view.RestoreScroll();
            //int displyColumnIndex = view.FirstDisplayedScrollingColumnIndex;
            //int displyRowIndex = view.FirstDisplayedScrollingRowIndex;
            view.Rows.Clear();
            if (_table is null) return;
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                var col = _table.Columns[i];
                int rowIndex = view.Rows.Add();
                var row = view.Rows[rowIndex];
                row.Height = 32;
                row.Cells["ColumnIndex"].Value = i + 1;
                row.Cells[nameof(col.ColumnName)].Value = col.ColumnName;
                row.Cells[nameof(col.ColumnNullable)].Value = col.ColumnNullable;
                row.Cells[nameof(col.ColumnPrimaryKey)].Value = col.ColumnPrimaryKey;
                row.Cells[nameof(col.ColumnRequired)].Value = col.ColumnRequired;
                row.Cells[nameof(col.ColumnText)].Value = col.ColumnText;
                row.Cells[nameof(col.ColumnType)].Value = col.ColumnType;
                row.Cells[nameof(col.ColumnTypeLength)].Value = col.ColumnTypeLength;
                row.Cells[nameof(col.ColumnTypeFloat)].Value = col.ColumnTypeFloat;
                row.Cells[nameof(col.ColumnVarType)].Value = col.ColumnVarType;
                row.Cells[nameof(col.ColumnDbName)].Value = col.ColumnDbName;
                row.Cells[nameof(col.ColumnMake)].Value = col.ColumnMake;
                row.Cells[nameof(col.ColumnIndexer)].Value = col.ColumnIndexer;
                row.Cells[nameof(col.ColumnUnique)].Value = col.ColumnUnique;
            }
            //view.FirstDisplayedScrollingColumnIndex = displyColumnIndex;
            //view.FirstDisplayedScrollingRowIndex = displyRowIndex;
            view.ResetScroll();
        }

        // 显示表属性
        private void ShowTables()
        {
            var view = this.dataGridView2;
            view.Rows.Clear();
            for (int i = 0; i < _setting.TableProperties.Count; i++)
            {
                var pro = _setting.TableProperties[i];
                int rowIndex = view.Rows.Add();
                var row = view.Rows[rowIndex];
                row.Height = 28;
                row.Cells[0].Value = pro.Name;
                if (_table != null)
                {
                    if (_table.Properties.ContainsKey(pro.Name)) row.Cells[1].Value = _table.Properties[pro.Name];
                }
            }
        }

        // 更新表格索引号
        private void UpdateRowIndex()
        {
            var view = this.dataGridView1;
            for (int i = 0; i < view.Rows.Count; i++)
            {
                var row = view.Rows[i];
                row.Height = 32;
                row.Cells["ColumnIndex"].Value = i + 1;
            }
        }

        #endregion

        #region [=====数据操作=====]

        // 填充表格到对象
        private void FillGirdToTable()
        {
            var view1 = this.dataGridView1;
            var view2 = this.dataGridView2;
            view1.EndEdit();
            view2.EndEdit();
            // 填充列信息
            _table.Columns.Clear();
            for (int i = 0; i < view1.Rows.Count; i++)
            {
                TableColumn col = new TableColumn();
                var row = view1.Rows[i];
                col.ColumnName = ParseString(row.Cells[nameof(col.ColumnName)].Value);
                col.ColumnNullable = ParseBoolean(row.Cells[nameof(col.ColumnNullable)].Value);
                col.ColumnPrimaryKey = ParseBoolean(row.Cells[nameof(col.ColumnPrimaryKey)].Value);
                col.ColumnRequired = ParseBoolean(row.Cells[nameof(col.ColumnRequired)].Value);
                col.ColumnText = ParseString(row.Cells[nameof(col.ColumnText)].Value);
                col.ColumnType = ParseString(row.Cells[nameof(col.ColumnType)].Value);
                col.ColumnTypeLength = ParseInt(row.Cells[nameof(col.ColumnTypeLength)].Value);
                col.ColumnTypeFloat = ParseInt(row.Cells[nameof(col.ColumnTypeFloat)].Value);
                col.ColumnVarType = ParseString(row.Cells[nameof(col.ColumnVarType)].Value);
                col.ColumnDbName = ParseString(row.Cells[nameof(col.ColumnDbName)].Value);
                col.ColumnRequired = ParseBoolean(row.Cells[nameof(col.ColumnRequired)].Value);
                col.ColumnMake = ParseBoolean(row.Cells[nameof(col.ColumnMake)].Value);
                col.ColumnIndexer = ParseBoolean(row.Cells[nameof(col.ColumnIndexer)].Value);
                col.ColumnUnique = ParseBoolean(row.Cells[nameof(col.ColumnUnique)].Value);
                _table.Columns.Add(col);
            }
            // 填充属性信息
            _table.Properties.Clear();
            for (int i = 0; i < view2.Rows.Count; i++)
            {
                var row = view2.Rows[i];
                _table.Properties[(string)row.Cells[0].Value] = (string)row.Cells[1].Value;
            }
        }

        private void OpenFile(string path)
        {
            if (!System.IO.File.Exists(path)) throw new Exception("文件不存在");

            // 判断当前是否有路径
            if (string.IsNullOrWhiteSpace(_path))
            {
                _path = path;
                using (var f = System.IO.File.Open(_path, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                {
                    byte[] bytes = new byte[f.Length];
                    f.Position = 0;
                    f.Read(bytes, 0, bytes.Length);
                    string content = System.Text.Encoding.UTF8.GetString(bytes);
                    _table = JsonConvert.DeserializeObject<Table>(content);
                    this.Text = $"{System.IO.Path.GetFileNameWithoutExtension(path)} - {Application.ProductName} Ver:{Application.ProductVersion} - [{path}]";
                    //MessageBox.Show(table.TableText);
                    ShowTables();
                    ShowColumns();
                }
            }
            else
            {
                // 启动一个新程序来运行
                ProcessStartInfo info = new ProcessStartInfo();
                info.FileName = _exePath;
                info.Arguments = $"\"{path}\"";
                info.UseShellExecute = true;
                info.CreateNoWindow = false;
                var pro = Process.Start(info);
            }
        }

        // 打开
        private void OpenFile()
        {
            // 自动保存
            //AutoSave();
            using (OpenFileDialog f = new OpenFileDialog())
            {
                f.Filter = "Json文件(*.json)|*.json";
                if (f.ShowDialog() == DialogResult.OK)
                {
                    OpenFile(f.FileName);
                }
            }
        }

        // 保存数据文件
        private void SaveDataFile()
        {
            SetStatus("正在保存数据文件 ...");
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                var col = _table.Columns[i];
                if (!string.IsNullOrWhiteSpace(col.ColumnName)) if (!_data.ColumnNames.Contains(col.ColumnName)) _data.ColumnNames.Add(col.ColumnName);
                if (!string.IsNullOrWhiteSpace(col.ColumnText)) if (!_data.ColumnTexts.Contains(col.ColumnText)) _data.ColumnTexts.Add(col.ColumnText);
                if (!string.IsNullOrWhiteSpace(col.ColumnType)) if (!_data.ColumnTypes.Contains(col.ColumnType)) _data.ColumnTypes.Add(col.ColumnType);
                if (!string.IsNullOrWhiteSpace(col.ColumnVarType)) if (!_data.ColumnVarTypes.Contains(col.ColumnVarType)) _data.ColumnVarTypes.Add(col.ColumnVarType);
            }
            // 数据排序
            _data.ColumnNames.Sort();
            _data.ColumnTexts.Sort();
            _data.ColumnTypes.Sort();
            _data.ColumnVarTypes.Sort();
            string content = JsonConvert.SerializeObject(_data);
            byte[] bytes = System.Text.Encoding.UTF8.GetBytes(content);
            using (var f = System.IO.File.Open(_pathData, System.IO.FileMode.Create, System.IO.FileAccess.Write))
            {
                f.Position = 0;
                f.Write(bytes, 0, bytes.Length);
            }
            SetStatus("数据文件保存成功");
        }

        private void SaveFileAs(string path)
        {
            // 保存数据文件
            SaveDataFile();
            string content = JsonConvert.SerializeObject(_table);
            byte[] bytes = System.Text.Encoding.UTF8.GetBytes(content);
            using (var f = System.IO.File.Open(path, System.IO.FileMode.Create, System.IO.FileAccess.Write))
            {
                f.Position = 0;
                f.Write(bytes, 0, bytes.Length);
            }
            if (_path != path)
            {
                _path = path;
                this.Text = $"{System.IO.Path.GetFileNameWithoutExtension(path)} - {Application.ProductName} Ver:{Application.ProductVersion} - [{path}]";
            }
        }

        private void SaveNewFile()
        {
            using (SaveFileDialog f = new SaveFileDialog())
            {
                string tabName = "";
                if (_table.Properties.ContainsKey("Name")) tabName = _table.Properties["Name"];
                if (!string.IsNullOrWhiteSpace(tabName)) f.FileName = tabName + ".json";
                f.Filter = "Json文件(*.json)|*.json";
                if (f.ShowDialog() == DialogResult.OK)
                {
                    SaveFileAs(f.FileName);
                }
            }
        }

        private void SaveFile()
        {
            // 填充对象
            FillGirdToTable();
            if (string.IsNullOrWhiteSpace(_path))
            {
                SaveNewFile();
            }
            else
            {
                SaveFileAs(_path);
            }
        }

        private void AutoSave()
        {
            if (!string.IsNullOrWhiteSpace(_path))
            {
                if (MessageBox.Show("需要对当前文件先进行保存吗?", "保存提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
                {
                    SetStatus("正在保存 ...");
                    SaveFile();
                    SetStatus("保存成功");
                }
            }
        }

        #endregion

        #region [=====列表操作=====]

        // 上移
        private void MoveUp()
        {
            var view = this.dataGridView1;
            int scrollTop = view.VerticalScrollingOffset;
            int scrollLeft = view.HorizontalScrollingOffset;
            if (view.SelectedRows.Count <= 0) { MessageBox.Show("请先选择一条"); return; }
            int rowIndex = view.SelectedRows[0].Index;
            if (rowIndex > 0)
            {
                // 填充对象
                FillGirdToTable();
                var colTemp = _table.Columns[rowIndex];
                _table.Columns[rowIndex] = _table.Columns[rowIndex - 1];
                _table.Columns[rowIndex - 1] = colTemp;
                // 重新刷新所有列
                ShowColumns();
                // 重新选中行
                view.Rows[rowIndex - 1].Selected = true;
                view.FirstDisplayedScrollingRowIndex = rowIndex - 1;
            }
            //view.AutoScrollOffset = new Point(scrollLeft, scrollTop);

        }

        // 下移
        private void MoveDown()
        {
            var view = this.dataGridView1;
            //int scrollTop = view.VerticalScrollingOffset;
            //int scrollLeft = view.HorizontalScrollingOffset;
            //view.
            if (view.SelectedRows.Count <= 0) { MessageBox.Show("请先选择一条"); return; }
            int rowIndex = view.SelectedRows[0].Index;
            if (rowIndex < view.Rows.Count - 1)
            {
                // 填充对象
                FillGirdToTable();
                var colTemp = _table.Columns[rowIndex];
                _table.Columns[rowIndex] = _table.Columns[rowIndex + 1];
                _table.Columns[rowIndex + 1] = colTemp;
                // 重新刷新所有列
                ShowColumns();
                // 重新选中行
                view.Rows[rowIndex + 1].Selected = true;
                view.FirstDisplayedScrollingRowIndex = rowIndex + 1;
            }
            //view.AutoScrollOffset = new Point(scrollLeft, scrollTop);
        }

        // 显示辅助下拉列表
        private void ShowEdListBox()
        {
            var colName = _editListBox.DataGridView.Columns[_editListBox.ColumnIndex].Name;
            _editListBox.Items.Clear();
            switch (colName)
            {
                case "ColumnName":
                    if (string.IsNullOrWhiteSpace(_editValue))
                    {
                        _editListBox.Items.AddRange(_data.ColumnNames.ToArray());
                    }
                    else
                    {
                        _editListBox.Items.AddRange(_data.ColumnNames.Where(d => d.StartsWith(_editValue)).ToArray());
                    }
                    break;
                case "ColumnText":
                    if (string.IsNullOrWhiteSpace(_editValue))
                    {
                        _editListBox.Items.AddRange(_data.ColumnTexts.ToArray());
                    }
                    else
                    {
                        _editListBox.Items.AddRange(_data.ColumnTexts.Where(d => d.StartsWith(_editValue)).ToArray());
                    }
                    break;
                case "ColumnType":
                    if (string.IsNullOrWhiteSpace(_editValue))
                    {
                        _editListBox.Items.AddRange(_data.ColumnTypes.ToArray());
                    }
                    else
                    {
                        _editListBox.Items.AddRange(_data.ColumnTypes.Where(d => d.StartsWith(_editValue)).ToArray());
                    }
                    break;
                case "ColumnVarType":
                    if (string.IsNullOrWhiteSpace(_editValue))
                    {
                        _editListBox.Items.AddRange(_data.ColumnVarTypes.ToArray());
                    }
                    else
                    {
                        _editListBox.Items.AddRange(_data.ColumnVarTypes.Where(d => d.StartsWith(_editValue)).ToArray());
                    }
                    break;
            }
            if (_editListBox.Items.Count <= 0) _editListBox.Visible = false;
        }

        // 添加行
        private void AddRow()
        {
            var view = this.dataGridView1;
            var rowIndex = view.Rows.Add();
            var row = view.Rows[rowIndex];
            row.Cells["ColumnType"].Value = "varchar";
            row.Cells["ColumnVarType"].Value = "string";
            row.Cells["ColumnTypeLength"].Value = 0;
            row.Cells["ColumnTypeFloat"].Value = 0;
            row.Cells["ColumnNullable"].Value = true;
            row.Cells["ColumnMake"].Value = true;
            UpdateRowIndex();
        }

        // 删除行
        private void DeleteRow()
        {
            var view = this.dataGridView1;
            if (view.SelectedRows.Count <= 0) { MessageBox.Show("请先选择一条"); return; }
            int rowIndex = view.SelectedRows[0].Index;
            if (MessageBox.Show($"确定要删除第{rowIndex + 1}行吗?", "删除提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
            {
                view.Rows.RemoveAt(rowIndex);
                UpdateRowIndex();
            }
        }

        #endregion

        // 获取类型的默认值
        private string GetDefaultValue(string typeName)
        {
            switch (typeName)
            {
                case "string": return "string.Empty";
                case "byte":
                case "short":
                case "int":
                case "long":
                case "ushort":
                case "uint":
                case "ulong":
                case "float":
                case "double":
                case "decimal":
                    return "0";
                case "bool":
                    return "false";
                case "DateTime": return "DateTime.Now";
                default: return string.Empty;
            }
        }

        private void 打开OToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFile();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.Text = $"{Application.ProductName} Ver:{Application.ProductVersion}";
            // 添加列表控件
            _editListBox = new EdListBox(this.dataGridView1);
            this.Controls.Add(_editListBox);
            _editListBox.Name = "editListBox";
            _editListBox.Size = new Size(150, 200);
            _editListBox.Parent = this;
            _editListBox.Visible = false;
            _editListBox.BringToFront();
            _editControlWorking = false;
            _localPath = AppDomain.CurrentDomain.BaseDirectory;
            if (!_localPath.EndsWith("\\")) _localPath += "\\";
            _exePath = Application.ExecutablePath;
            _localConfigPath = $"{_localPath}config\\";
            if (!System.IO.Directory.Exists(_localConfigPath)) System.IO.Directory.CreateDirectory(_localConfigPath);
            using (var f = System.IO.File.Open($"{_localConfigPath}setting.json", System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                byte[] bytes = new byte[f.Length];
                f.Position = 0;
                f.Read(bytes, 0, bytes.Length);
                string content = System.Text.Encoding.UTF8.GetString(bytes);
                _setting = JsonConvert.DeserializeObject<Configs.Setting>(content);
            }
            _pathData = $"{_localConfigPath}data.json";
            if (System.IO.File.Exists(_pathData))
            {
                using (var f = System.IO.File.Open(_pathData, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                {
                    byte[] bytes = new byte[f.Length];
                    f.Position = 0;
                    f.Read(bytes, 0, bytes.Length);
                    string content = System.Text.Encoding.UTF8.GetString(bytes);
                    _data = JsonConvert.DeserializeObject<Configs.Data>(content);
                    if (_data.ColumnNames is null) _data.ColumnNames = new List<string>();
                    if (_data.ColumnTexts is null) _data.ColumnTexts = new List<string>();
                    if (_data.ColumnTypes is null) _data.ColumnTypes = new List<string>();
                    if (_data.ColumnVarTypes is null) _data.ColumnVarTypes = new List<string>();
                }
            }
            else
            {
                _data = new Configs.Data();
                _data.ColumnNames = new List<string>();
                _data.ColumnTexts = new List<string>();
                _data.ColumnTypes = new List<string>();
            }
            //var cmb = (DataGridViewComboBoxColumn)this.dataGridView1.Columns["ColumnType"];
            //for (int i = 0; i < _setting.ColumnTypes.Count; i++)
            //{
            //    cmb.Items.Add(_setting.ColumnTypes[i].Name);
            //}
            _path = null;
            _table = new Table();
            _table.Columns = new List<TableColumn>();
            _table.Properties = new Dictionary<string, string>();
            ShowColumns();
            ShowTables();
            if (!string.IsNullOrWhiteSpace(this.InitPath)) OpenFile(this.InitPath);
            SetStatus("就绪");
        }

        private void 保存SToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetStatus("正在保存 ...");
            SaveFile();
            SetStatus("保存成功");
        }

        private void toolAddRow_Click(object sender, EventArgs e)
        {
            AddRow();
        }

        private void toolDeleteRow_Click(object sender, EventArgs e)
        {
            DeleteRow();
        }

        private void 保存SToolStripButton_Click(object sender, EventArgs e)
        {
            SetStatus("正在保存 ...");
            SaveFile();
            SetStatus("保存成功");
        }

        private void 打开OToolStripButton_Click(object sender, EventArgs e)
        {
            OpenFile();
        }

        private void 另存为AToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 填充对象
            FillGirdToTable();
            SaveNewFile();
        }

        private void 新建NToolStripButton_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(_path)) return;
            // 启动一个新程序来运行
            ProcessStartInfo info = new ProcessStartInfo();
            info.FileName = _exePath;
            info.UseShellExecute = true;
            info.CreateNoWindow = false;
            var pro = Process.Start(info);
        }

        private void dataGridView1_DragDrop(object sender, DragEventArgs e)
        {
            //MessageBox.Show("OK");
            var files = (string[])e.Data.GetData(DataFormats.FileDrop, false);
            if (files.Length > 0)
            {
                string filePath = files[0];
                switch (System.IO.Path.GetExtension(filePath).ToLower())
                {
                    case ".json":
                        // 自动保存
                        AutoSave();
                        OpenFile(filePath);
                        break;
                    case ".dll":
                        if (!string.IsNullOrWhiteSpace(_path))
                        {
                            MessageBox.Show("请新建一个界面执行导入");
                            return;
                        }
                        using (FrmImport frm = new FrmImport())
                        {
                            frm.LoadDll(filePath);
                            if (frm.ShowDialog() == DialogResult.OK)
                            {
                                _table = frm.Table;
                                ShowTables();
                                ShowColumns();
                            }
                        }
                        break;
                    default:
                        MessageBox.Show($"不支持的文件类型'{System.IO.Path.GetExtension(filePath).ToLower()}'");
                        break;
                }
;
            }

        }

        private void dataGridView1_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.Move;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {

        }

        private void toolMakeCSharp_Click(object sender, EventArgs e)
        {
            // 填充对象
            FillGirdToTable();
            StringBuilder sb = new StringBuilder();
            string tabSchema = "";
            if (_table.Properties.ContainsKey("Schema")) tabSchema = _table.Properties["Schema"];
            string tabInherit = "";
            if (_table.Properties.ContainsKey("Inherit")) tabInherit = ": " + _table.Properties["Inherit"];
            string tabName = "";
            if (_table.Properties.ContainsKey("Name")) tabName = _table.Properties["Name"];
            string tabDbName = "";
            if (_table.Properties.ContainsKey("DbName")) tabDbName = _table.Properties["DbName"];
            string tabText = "";
            if (_table.Properties.ContainsKey("Text")) tabText = _table.Properties["Text"];
            sb.AppendLine($"/// <summary>");
            sb.AppendLine($"/// {tabText}");
            sb.AppendLine($"/// </summary>");
            sb.AppendLine($"[Table(\"{tabDbName}\", Schema = \"{tabSchema}\")]");
            sb.AppendLine($"[Description(\"{tabText}\")]");
            sb.AppendLine($"public class {tabName} {tabInherit} {{");
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                var col = _table.Columns[i];
                if (col.ColumnMake)
                {
                    var colType = _setting.ColumnTypes.Where(d => d.Name == col.ColumnType).FirstOrDefault();
                    var colTypeCSharp = col.ColumnVarType;
                    if (string.IsNullOrWhiteSpace(colTypeCSharp)) colTypeCSharp = "string";
                    if (col.ColumnNullable && colTypeCSharp != "string")
                    {
                        colTypeCSharp += "?";
                    }
                    sb.AppendLine($"    /// <summary>");
                    sb.AppendLine($"    /// {col.ColumnText}");
                    sb.AppendLine($"    /// </summary>");
                    switch (col.ColumnType)
                    {
                        case "varchar":
                            if (col.ColumnTypeLength > 0)
                            {
                                sb.AppendLine($"    [Column(\"{col.ColumnDbName}\", TypeName = \"{col.ColumnType}({col.ColumnTypeLength})\")]");
                            }
                            else
                            {
                                sb.AppendLine($"    [Column(\"{col.ColumnDbName}\", TypeName = \"{col.ColumnType}\")]");
                            }
                            sb.AppendLine($"    [StringLength({col.ColumnTypeLength})]");
                            break;
                        case "decimal":
                            if (col.ColumnTypeLength <= 0)
                            {
                                MessageBox.Show($"字段'{col.ColumnName}'类型'{col.ColumnType}'长度不能为0");
                                return;
                            }
                            sb.AppendLine($"    [Column(\"{col.ColumnDbName}\", TypeName = \"{col.ColumnType}({col.ColumnTypeLength},{col.ColumnTypeFloat})\")]");
                            break;
                        default:
                            sb.AppendLine($"    [Column(\"{col.ColumnDbName}\", TypeName = \"{col.ColumnType}\")]");
                            break;
                    }
                    sb.AppendLine($"    [Description(\"{col.ColumnText}\")]");
                    sb.Append($"    public virtual {colTypeCSharp} {col.ColumnName} {{ get; set; }}");
                    // 根据是否为空填充默认数据
                    if (!col.ColumnNullable)
                    {
                        string defaultValue = GetDefaultValue(colTypeCSharp);
                        if (!string.IsNullOrWhiteSpace(defaultValue))
                        {
                            sb.Append($" = {defaultValue};");
                        }
                    }
                    sb.AppendLine();
                }
            }
            sb.AppendLine($"}}");
            FrmText frm = new FrmText();
            frm.Text = $"代码生成 - C#类 - [{tabText}({tabName})]";
            frm.ContentTextBox.Text = sb.ToString();
            frm.Show();
        }

        private void toolMoveUp_Click(object sender, EventArgs e)
        {
            MoveUp();
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            MoveUp();
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            MoveDown();
        }

        private void toolMoveDown_Click(object sender, EventArgs e)
        {
            MoveDown();
        }

        private void toolMakePgTable2_Click(object sender, EventArgs e)
        {
            
        }

        private void toolMakePgAlter2_Click(object sender, EventArgs e)
        {
            // 填充对象
            FillGirdToTable();
            StringBuilder sb = new StringBuilder();
            string tabSchema = "";
            if (_table.Properties.ContainsKey("Schema")) tabSchema = _table.Properties["Schema"];
            string tabInherit = "";
            if (_table.Properties.ContainsKey("Inherit")) tabInherit = ": " + _table.Properties["Inherit"];
            string tabName = "";
            if (_table.Properties.ContainsKey("Name")) tabName = _table.Properties["DbName"];
            string tabText = "";
            if (_table.Properties.ContainsKey("Text")) tabText = _table.Properties["Text"];
            string tabFullName = (string.IsNullOrWhiteSpace(tabSchema) ? "" : tabSchema + ".") + tabName;
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                var col = _table.Columns[i];
                var colType = col.ColumnType;
                switch (col.ColumnType)
                {
                    case "varchar":
                        if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength})";
                        break;
                    case "decimal":
                        if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength},{col.ColumnTypeFloat})";
                        break;
                }
                sb.AppendLine($"-- 在 {tabText} 表中添加 {col.ColumnText} 字段");
                sb.AppendLine($"alter table {tabFullName} add \"{col.ColumnDbName}\" {colType} {(col.ColumnNullable ? "NULL" : "NOT NULL")};");
                sb.AppendLine($"-- 更新 {tabText} 表中的 {col.ColumnText} 字段");
                sb.AppendLine($"alter table {tabFullName} alter column \"{col.ColumnDbName}\" type {colType} using {GetUnderScoreCase(col.ColumnName)}::{colType};");
                if (col.ColumnNullable)
                {
                    sb.AppendLine($"-- 设置 {tabText} 表中的 {col.ColumnText} 字段可为空");
                    sb.AppendLine($"alter table {tabFullName} alter column \"{col.ColumnDbName}\" drop NOT NULL;");
                }
                else
                {
                    sb.AppendLine($"-- 设置 {tabText} 表中的 {col.ColumnText} 字段不可为空");
                    sb.AppendLine($"alter table {tabFullName} alter column \"{col.ColumnDbName}\" set NOT NULL;");
                }
                sb.AppendLine($"-- 设置 {tabText} 表的 {col.ColumnText} 字段描述");
                sb.AppendLine($"COMMENT ON COLUMN {tabFullName}.{col.ColumnDbName} IS '{col.ColumnText}';");
                sb.AppendLine();
                if (col.ColumnIndexer)
                {
                    if (col.ColumnUnique)
                    {
                        sb.AppendLine($"-- 设置 {tabText} 表的 {col.ColumnText} 为唯一索引字段");
                        sb.AppendLine($"CREATE UNIQUE INDEX {tabName}_{col.ColumnDbName}_idx ON {tabFullName} USING btree ({col.ColumnDbName});");
                    }
                    else
                    {
                        sb.AppendLine($"-- 设置 {tabText} 表的 {col.ColumnText} 为索引字段");
                        sb.AppendLine($"CREATE INDEX {tabName}_{col.ColumnDbName}_idx ON {tabFullName} ({col.ColumnDbName});");
                    }
                }
            }
            FrmText frm = new FrmText();
            frm.Text = $"Sql生成 - 表更更新 - [{tabText}({tabName})]";
            frm.ContentTextBox.Text = sb.ToString();
            frm.Show();
        }

        private void 退出XToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void toolMakeCSharpDto_Click(object sender, EventArgs e)
        {
            // 填充对象
            FillGirdToTable();
            StringBuilder sb = new StringBuilder();
            string tabSchema = "";
            if (_table.Properties.ContainsKey("Schema")) tabSchema = _table.Properties["Schema"];
            string tabInherit = "";
            if (_table.Properties.ContainsKey("Inherit")) tabInherit = ": " + _table.Properties["Inherit"];
            string tabName = "";
            if (_table.Properties.ContainsKey("Name")) tabName = _table.Properties["Name"];
            string tabText = "";
            if (_table.Properties.ContainsKey("Text")) tabText = _table.Properties["Text"];
            sb.AppendLine($"/// <summary>");
            sb.AppendLine($"/// {tabText}");
            sb.AppendLine($"/// </summary>");
            sb.AppendLine($"public class {tabName}Dto {{");
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                var col = _table.Columns[i];
                if (col.ColumnMake)
                {
                    var colTypeCSharp = col.ColumnVarType;
                    if (string.IsNullOrWhiteSpace(colTypeCSharp)) colTypeCSharp = "string";
                    if (col.ColumnNullable && colTypeCSharp != "string")
                    {
                        colTypeCSharp += "?";
                    }
                    sb.AppendLine($"{Space(4)}/// <summary>");
                    sb.AppendLine($"{Space(4)}/// {col.ColumnText}");
                    sb.AppendLine($"{Space(4)}/// </summary>");
                    if (col.ColumnRequired) sb.AppendLine($"{Space(4)}[Required]");
                    sb.Append($"{Space(4)}public virtual {colTypeCSharp} {col.ColumnName} {{ get; set; }}");
                    // 根据是否为空填充默认数据
                    if (!col.ColumnNullable)
                    {
                        string defaultValue = GetDefaultValue(colTypeCSharp);
                        if (!string.IsNullOrWhiteSpace(defaultValue))
                        {
                            sb.Append($" = {defaultValue};");
                        }
                    }
                    sb.AppendLine();
                }
            }
            sb.AppendLine($"}}");
            FrmText frm = new FrmText();
            frm.Text = $"代码生成 - C#Dto类 - [{tabText}({tabName})]";
            frm.ContentTextBox.Text = sb.ToString();
            frm.Show();
        }

        private void toolMakeCSharpLinqSelect_Click(object sender, EventArgs e)
        {
            // 填充对象
            FillGirdToTable();
            StringBuilder sb = new StringBuilder();
            string tabAbbr = "";
            if (_table.Properties.ContainsKey("Abbr")) tabAbbr = _table.Properties["Abbr"];
            string tabSchema = "";
            if (_table.Properties.ContainsKey("Schema")) tabSchema = _table.Properties["Schema"];
            string tabInherit = "";
            if (_table.Properties.ContainsKey("Inherit")) tabInherit = ": " + _table.Properties["Inherit"];
            string tabName = "";
            if (_table.Properties.ContainsKey("Name")) tabName = _table.Properties["Name"];
            string tabText = "";
            if (_table.Properties.ContainsKey("Text")) tabText = _table.Properties["Text"];
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                var col = _table.Columns[i];
                sb.AppendLine($"{col.ColumnName} = {tabAbbr}.{col.ColumnName},");
            }
            FrmText frm = new FrmText();
            frm.Text = $"代码生成 - C#中Linq查询字段 - [{tabText}({tabName})]";
            frm.ContentTextBox.Text = sb.ToString();
            frm.Show();
        }

        private void toolMakeCSharpEntityCopy_Click(object sender, EventArgs e)
        {
            // 填充对象
            FillGirdToTable();
            StringBuilder sb = new StringBuilder();
            string tabAbbr = "";
            if (_table.Properties.ContainsKey("Abbr")) tabAbbr = _table.Properties["Abbr"];
            string tabSchema = "";
            if (_table.Properties.ContainsKey("Schema")) tabSchema = _table.Properties["Schema"];
            string tabInherit = "";
            if (_table.Properties.ContainsKey("Inherit")) tabInherit = ": " + _table.Properties["Inherit"];
            string tabName = "";
            if (_table.Properties.ContainsKey("Name")) tabName = _table.Properties["Name"];
            string tabText = "";
            if (_table.Properties.ContainsKey("Text")) tabText = _table.Properties["Text"];
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                var col = _table.Columns[i];
                if (!col.ColumnPrimaryKey) sb.AppendLine($"info.{col.ColumnName} = input.{col.ColumnName};");
            }
            FrmText frm = new FrmText();
            frm.Text = $"代码生成 - C#中Linq查询字段 - [{tabText}({tabName})]";
            frm.ContentTextBox.Text = sb.ToString();
            frm.Show();
        }

        private void dataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e)
        {
            Debug.WriteLine($"[dataGridView1_CellEnter] Column: {e.ColumnIndex}, Row: {e.RowIndex}");
            // 默认隐藏列表
            _editListBox.Visible = false;
            _editListBox.DataGridView.IsExternalControl = false;
            var view1 = this.dataGridView1;
            var colName = view1.Columns[e.ColumnIndex].Name;
            Debug.WriteLine($"[dataGridView1_CellEnter] {colName}");
            switch (colName)
            {
                case "ColumnName":
                case "ColumnText":
                case "ColumnVarType":
                case "ColumnType":
                    DataGridViewTextBoxCell txtCell = (DataGridViewTextBoxCell)view1.Rows[e.RowIndex].Cells[e.ColumnIndex];
                    if (txtCell.Value is null)
                    {
                        _editValue = "";
                    }
                    else
                    {
                        _editValue = (string)txtCell.Value;
                    }
                    _editListBox.IsWorking = true;
                    _editListBox.ColumnIndex = e.ColumnIndex;
                    _editListBox.RowIndex = e.RowIndex;
                    break;
                default:
                    _editListBox.IsWorking = false;
                    break;
            }
        }

        private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
            var view1 = this.dataGridView1;
            if (e.Control is DataGridViewTextBoxEditingControl)
            {
                DataGridViewTextBoxEditingControl txtControl = (DataGridViewTextBoxEditingControl)e.Control;
                if (!_editControlWorking)
                {
                    txtControl.TextChanged += TxtControl_TextChanged;
                    txtControl.KeyDown += TxtControl_KeyDown;
                    txtControl.PreviewKeyDown += TxtControl_PreviewKeyDown;
                    _editControlWorking = true;
                    _editListBox.EditingControl = txtControl;
                }
            }
        }

        private void TxtControl_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            //if (!_editListBox.IsWorking) return;
            DataGridViewTextBoxEditingControl txtControl = (DataGridViewTextBoxEditingControl)sender;
            switch (e.KeyCode)
            {
                case Keys.Down:
                    if (_editListBox.Visible)
                    {
                        if (_editListBox.Items.Count <= 0) return;
                        if (_editListBox.SelectedIndex < _editListBox.Items.Count - 1) _editListBox.SelectedIndex++;
                    }
                    break;
                case Keys.Up:
                    if (_editListBox.Visible)
                    {
                        if (_editListBox.Items.Count <= 0) return;
                        if (_editListBox.SelectedIndex > 0) _editListBox.SelectedIndex--;
                    }
                    break;
                case Keys.Enter:
                    if (_editListBox.Visible)
                    {
                        _editListBox.UpdateValueToDataGridView();
                        txtControl.EditingControlWantsInputKey(Keys.Enter, false);
                    }
                    break;
            }
        }

        private void TxtControl_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Up:
                case Keys.Down:
                case Keys.Enter:
                    e.Handled = false;
                    e.SuppressKeyPress = true;
                    break;
            }
        }

        private void TxtControl_TextChanged(object sender, EventArgs e)
        {
            DataGridViewTextBoxEditingControl txtControl = (DataGridViewTextBoxEditingControl)sender;
            Debug.WriteLine($"[TxtControl_TextChanged] '{txtControl.Text}'~'{_editValue}'");
            if (txtControl.Text != _editValue && _editListBox.IsWorking && !_editListBox.IsUpdating)
            {
                _editValue = txtControl.Text;
                Point p = txtControl.Parent.GetPositionInForm();
                _editListBox.Location = new Point(p.X, p.Y + txtControl.Parent.Height);
                _editListBox.Visible = true;
                _editListBox.DataGridView.IsExternalControl = true;
                // 显示下拉列表
                ShowEdListBox();
            }
            Debug.WriteLine(txtControl.Text);
        }

        private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            // 隐藏列表
            if (_editListBox.Focused) return;
            _editListBox.IsWorking = false;
            _editListBox.Visible = false;
            _editListBox.DataGridView.IsExternalControl = false;
            //Debug.WriteLine($"[dataGridView1_CellEndEdit] {e.ColumnIndex} {e.RowIndex}");
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {

        }

        private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.Up:
                case Keys.Down:
                case Keys.Enter:
                    e.Handled = false;
                    e.SuppressKeyPress = true;
                    break;
            }
        }

        private void dataGridView1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {

        }

        private void toolMakeDrawIO_Click(object sender, EventArgs e)
        {
            SetStatus("正在生成Xml内容 ...");
            // 填充对象
            FillGirdToTable();
            StringBuilder sb = new StringBuilder();
            string tabAbbr = "";
            if (_table.Properties.ContainsKey("Abbr")) tabAbbr = _table.Properties["Abbr"];
            string tabSchema = "";
            if (_table.Properties.ContainsKey("Schema")) tabSchema = _table.Properties["Schema"];
            string tabInherit = "";
            if (_table.Properties.ContainsKey("Inherit")) tabInherit = ": " + _table.Properties["Inherit"];
            string tabName = "";
            if (_table.Properties.ContainsKey("Name")) tabName = _table.Properties["Name"];
            string tabText = "";
            if (_table.Properties.ContainsKey("Text")) tabText = _table.Properties["Text"];

            int cellIndex = 1;
            int cellWidth = 320;
            int cellHeight = 30;
            int cellTop = 0;

            sb.AppendLine($"<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            sb.AppendLine($"<mxfile host=\"Electron\" modified=\"2022-10-29T08:25:12.948Z\" agent=\"5.0(Windows NT 10.0; Win64; x64) AppleWebKit/537.36(KHTML, like Gecko) draw.io/15.7.3 Chrome/91.0.4472.164 Electron/13.6.1 Safari/537.36\" etag=\"F2M1SoqM8tFXXiiPF2nf\" version=\"15.7.3\" type=\"device\">");
            sb.AppendLine($"{Space(2)}<diagram id=\"st6YKaS4vdsvS-INL8j-\" name=\"第 1 页\">");
            sb.AppendLine($"{Space(4)}<mxGraphModel dx=\"1102\" dy=\"865\" grid=\"1\" gridSize=\"10\" guides=\"1\" tooltips=\"1\" connect=\"1\" arrows=\"1\" fold=\"1\" page=\"1\" pageScale=\"1\" pageWidth=\"1200\" pageHeight=\"1600\" math=\"0\" shadow=\"0\">");
            sb.AppendLine($"{Space(6)}<root>");
            sb.AppendLine($"{Space(8)}<mxCell id=\"0\" />");
            sb.AppendLine($"{Space(8)}<mxCell id=\"1\" parent=\"0\" />");
            sb.AppendLine($"{Space(8)}<mxCell id=\"Zm8JS_GZHVNxTvJerJ6S-1\" value=\"{tabName}({tabText})\" style=\"shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;swimlaneFillColor=#FFFFFF;shadow=1;fillColor=#d5e8d4;strokeColor=#82b366;\" vertex=\"1\" parent=\"1\">");
            sb.AppendLine($"{Space(10)}<mxGeometry x=\"470\" y=\"360\" width=\"{cellWidth}\" height=\"{cellHeight * (_table.Columns.Count + 1) + 10}\" as=\"geometry\" />");
            sb.AppendLine($"{Space(8)}</mxCell>");

            // 生成所有的主键
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                var col = _table.Columns[i];
                if (col.ColumnPrimaryKey)
                {
                    cellIndex++;
                    cellTop += 30;
                    int colIndex = cellIndex;
                    string colType = col.ColumnType;
                    switch (col.ColumnType)
                    {
                        case "varchar":
                            if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength})";
                            break;
                        case "decimal":
                            if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength},{col.ColumnTypeFloat})";
                            break;
                    }
                    sb.AppendLine($"{Space(8)}<mxCell id=\"Zm8JS_GZHVNxTvJerJ6S-{colIndex}\" value=\"\" style=\"shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;top=0;left=0;bottom=1;right=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;\" vertex=\"1\" parent=\"Zm8JS_GZHVNxTvJerJ6S-1\">");
                    sb.AppendLine($"{Space(10)}<mxGeometry y=\"{cellTop}\" width=\"{cellWidth}\" height=\"{cellHeight}\" as=\"geometry\" />");
                    sb.AppendLine($"{Space(8)}</mxCell>");
                    cellIndex++;
                    sb.AppendLine($"{Space(8)}<mxCell id=\"Zm8JS_GZHVNxTvJerJ6S-{cellIndex}\" value=\"PK\" style=\"shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;\" vertex=\"1\" parent=\"Zm8JS_GZHVNxTvJerJ6S-{colIndex}\">");
                    sb.AppendLine($"{Space(10)}<mxGeometry width=\"{cellHeight}\" height=\"{cellHeight}\" as=\"geometry\">");
                    sb.AppendLine($"{Space(12)}<mxRectangle width=\"{cellHeight}\" height=\"{cellHeight}\" as=\"alternateBounds\" />");
                    sb.AppendLine($"{Space(10)}</mxGeometry>");
                    sb.AppendLine($"{Space(8)}</mxCell>");
                    cellIndex++;
                    sb.AppendLine($"{Space(8)}<mxCell id=\"Zm8JS_GZHVNxTvJerJ6S-{cellIndex}\" value=\"{col.ColumnDbName} {colType}\" style=\"shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;\" vertex=\"1\" parent=\"Zm8JS_GZHVNxTvJerJ6S-{colIndex}\">");
                    sb.AppendLine($"{Space(10)}<mxGeometry width=\"{cellHeight}\" height=\"{cellHeight}\" as=\"geometry\">");
                    sb.AppendLine($"{Space(12)}<mxRectangle width=\"{cellWidth - cellHeight}\" height=\"{cellHeight}\" as=\"alternateBounds\" />");
                    sb.AppendLine($"{Space(10)}</mxGeometry>");
                    sb.AppendLine($"{Space(8)}</mxCell>");
                }
            }
            // 生成所有的普通字段
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                var col = _table.Columns[i];
                if (!col.ColumnPrimaryKey)
                {
                    cellIndex++;
                    cellTop += 30;
                    int colIndex = cellIndex;
                    var colType = col.ColumnType;
                    switch (col.ColumnType)
                    {
                        case "varchar":
                            if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength})";
                            break;
                        case "decimal":
                            if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength},{col.ColumnTypeFloat})";
                            break;
                    }
                    sb.AppendLine($"{Space(8)}<mxCell id=\"Zm8JS_GZHVNxTvJerJ6S-{cellIndex}\" value=\"\" style=\"shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;top=0;left=0;bottom=0;right=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;\" vertex=\"1\" parent=\"Zm8JS_GZHVNxTvJerJ6S-1\">");
                    sb.AppendLine($"{Space(10)}<mxGeometry y=\"{cellTop}\" width=\"{cellWidth}\" height=\"{cellHeight}\" as=\"geometry\" />");
                    sb.AppendLine($"{Space(8)}</mxCell>");
                    cellIndex++;
                    sb.AppendLine($"{Space(8)}<mxCell id=\"Zm8JS_GZHVNxTvJerJ6S-{cellIndex}\" value=\"\" style=\"shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;\" vertex=\"1\" parent=\"Zm8JS_GZHVNxTvJerJ6S-{colIndex}\">");
                    sb.AppendLine($"{Space(10)}<mxGeometry width=\"{cellHeight}\" height=\"{cellHeight}\" as=\"geometry\">");
                    sb.AppendLine($"{Space(12)}<mxRectangle width=\"{cellHeight}\" height=\"{cellHeight}\" as=\"alternateBounds\" />");
                    sb.AppendLine($"{Space(10)}</mxGeometry>");
                    sb.AppendLine($"{Space(8)}</mxCell>");
                    cellIndex++;
                    sb.AppendLine($"{Space(8)}<mxCell id=\"Zm8JS_GZHVNxTvJerJ6S-{cellIndex}\" value=\"{col.ColumnDbName} {colType}: {col.ColumnText}\" style=\"shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;\" vertex=\"1\" parent=\"Zm8JS_GZHVNxTvJerJ6S-{colIndex}\">");
                    sb.AppendLine($"{Space(10)}<mxGeometry width=\"{cellHeight}\" height=\"{cellHeight}\" as=\"geometry\">");
                    sb.AppendLine($"{Space(12)}<mxRectangle width=\"{cellWidth - cellHeight}\" height=\"{cellHeight}\" as=\"alternateBounds\" />");
                    sb.AppendLine($"{Space(10)}</mxGeometry>");
                    sb.AppendLine($"{Space(8)}</mxCell>");
                }
            }
            sb.AppendLine($"{Space(6)}</root>");
            sb.AppendLine($"{Space(4)}</mxGraphModel>");
            sb.AppendLine($"{Space(2)}</diagram>");
            sb.AppendLine($"</mxfile>");
            SetStatus("生成Xml成功");
            using (SaveFileDialog f = new SaveFileDialog())
            {
                f.FileName = $"{tabName}.drawio.xml";
                f.Filter = "Xml文件(*.xml)|*.xml";
                if (f.ShowDialog() == DialogResult.OK)
                {
                    byte[] bytes = Encoding.UTF8.GetBytes(sb.ToString());
                    using (var fs = System.IO.File.Open(f.FileName, System.IO.FileMode.Create, System.IO.FileAccess.Write))
                    {
                        fs.Position = 0;
                        fs.Write(bytes, 0, bytes.Length);
                    }
                    SetStatus("导出成功");
                }
            }
        }

        private void toolMakeHtml_Click(object sender, EventArgs e)
        {
            SetStatus("正在生成Html内容 ...");
            // 填充对象
            FillGirdToTable();
            StringBuilder sb = new StringBuilder();
            string tabAbbr = "";
            if (_table.Properties.ContainsKey("Abbr")) tabAbbr = _table.Properties["Abbr"];
            string tabSchema = "";
            if (_table.Properties.ContainsKey("Schema")) tabSchema = _table.Properties["Schema"];
            string tabInherit = "";
            if (_table.Properties.ContainsKey("Inherit")) tabInherit = ": " + _table.Properties["Inherit"];
            string tabName = "";
            if (_table.Properties.ContainsKey("Name")) tabName = _table.Properties["Name"];
            string tabText = "";
            if (_table.Properties.ContainsKey("Text")) tabText = _table.Properties["Text"];

            int cellIndex = 1;
            int cellWidth = 320;
            int cellHeight = 30;
            int cellTop = 0;

            sb.AppendLine($"<html>");
            sb.AppendLine($"{Space(2)}<head>");
            sb.AppendLine($"{Space(4)}<title>{tabName}({tabText})</title>");
            sb.AppendLine($"{Space(2)}</head>");
            sb.AppendLine($"{Space(2)}<body>");
            sb.AppendLine($"{Space(4)}<table>");
            sb.AppendLine($"{Space(6)}<tr>");
            sb.AppendLine($"{Space(8)}<th>序号</th>");
            sb.AppendLine($"{Space(8)}<th>建模名称</th>");
            sb.AppendLine($"{Space(8)}<th>建模类型</th>");
            sb.AppendLine($"{Space(8)}<th>数据库字段</th>");
            sb.AppendLine($"{Space(8)}<th>数据库类型</th>");
            sb.AppendLine($"{Space(8)}<th>是否可为空</th>");
            sb.AppendLine($"{Space(8)}<th>字段说明</th>");
            sb.AppendLine($"{Space(8)}<th>数据来源</th>");
            sb.AppendLine($"{Space(8)}<th>来源字段</th>");
            sb.AppendLine($"{Space(6)}</tr>");

            // 生成所有的普通字段
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                var col = _table.Columns[i];
                cellIndex++;
                cellTop += 30;
                int colIndex = cellIndex;
                var colType = col.ColumnVarType;
                var colDbType = col.ColumnType;
                switch (colDbType)
                {
                    case "varchar":
                        if (col.ColumnTypeLength > 0) colDbType += $"({col.ColumnTypeLength})";
                        break;
                    case "decimal":
                        if (col.ColumnTypeLength > 0) colDbType += $"({col.ColumnTypeLength},{col.ColumnTypeFloat})";
                        break;
                }
                sb.AppendLine($"{Space(6)}<tr>");
                sb.AppendLine($"{Space(8)}<td>{i + 1}</td>");
                sb.AppendLine($"{Space(8)}<td>{col.ColumnName}</td>");
                sb.AppendLine($"{Space(8)}<td>{colType}</td>");
                sb.AppendLine($"{Space(8)}<td>{col.ColumnDbName}</td>");
                sb.AppendLine($"{Space(8)}<td>{colDbType}</td>");
                sb.AppendLine($"{Space(8)}<td>{(col.ColumnNullable ? "是" : "否")}</td>");
                sb.AppendLine($"{Space(8)}<td>{col.ColumnText}</td>");
                sb.AppendLine($"{Space(8)}<td>&nbsp;</td>");
                sb.AppendLine($"{Space(8)}<td>&nbsp;</td>");
                sb.AppendLine($"{Space(6)}</tr>");
            }
            sb.AppendLine($"{Space(4)}</table>");
            sb.AppendLine($"{Space(2)}</body>");
            sb.AppendLine($"</html>");
            SetStatus("生成Html成功");
            using (SaveFileDialog f = new SaveFileDialog())
            {
                f.FileName = $"{tabName}.html";
                f.Filter = "Html文件(*.html)|*.html";
                if (f.ShowDialog() == DialogResult.OK)
                {
                    byte[] bytes = Encoding.UTF8.GetBytes(sb.ToString());
                    using (var fs = System.IO.File.Open(f.FileName, System.IO.FileMode.Create, System.IO.FileAccess.Write))
                    {
                        fs.Position = 0;
                        fs.Write(bytes, 0, bytes.Length);
                    }
                    SetStatus("导出成功");
                    Process.Start(f.FileName);
                }
            }
        }

        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            AddRow();
        }

        private void toolStripButton4_Click(object sender, EventArgs e)
        {
            DeleteRow();
        }

        private void toolExportPostgre_Click(object sender, EventArgs e)
        {
            SetStatus("正在生成Sql内容 ...");
            // 读取预生成内容
            string path = $"{_localConfigPath}sql_pb.txt";
            string pbContent = "";
            if (!System.IO.File.Exists(path)) using (var f = System.IO.File.Create(path)) { };
            using (var f = System.IO.File.Open(path, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                byte[] bytes = new byte[f.Length];
                f.Position = 0;
                f.Read(bytes, 0, bytes.Length);
                pbContent = System.Text.Encoding.UTF8.GetString(bytes);
            }
            // 填充对象
            FillGirdToTable();
            StringBuilder sb = new StringBuilder();
            string tabSchema = "";
            if (_table.Properties.ContainsKey("Schema")) tabSchema = _table.Properties["Schema"];
            string tabInherit = "";
            if (_table.Properties.ContainsKey("Inherit")) tabInherit = ": " + _table.Properties["Inherit"];
            string tabName = "";
            if (_table.Properties.ContainsKey("Name")) tabName = _table.Properties["Name"];
            string tabText = "";
            if (_table.Properties.ContainsKey("Text")) tabText = _table.Properties["Text"];
            string tabFullName = (string.IsNullOrWhiteSpace(tabSchema) ? "" : tabSchema + ".") + _table.Properties["DbName"];
            string tabPrimaryKey = "";
            sb.AppendLine($"-- 添加{tabText}表");
            sb.AppendLine($"CREATE TABLE {tabFullName}(");
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                var col = _table.Columns[i];
                if (col.ColumnPrimaryKey)
                {
                    var colType = col.ColumnType;
                    switch (col.ColumnType)
                    {
                        case "varchar":
                            if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength})";
                            break;
                        case "decimal":
                            if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength},{col.ColumnTypeFloat})";
                            break;
                    }
                    //sb.AppendLine($"    -- {col.ColumnText}");
                    sb.AppendLine($"    \"{col.ColumnDbName}\" {colType} {(col.ColumnNullable ? "NULL" : "NOT NULL")},");
                    tabPrimaryKey = col.ColumnDbName;
                }
            }
            if (!string.IsNullOrWhiteSpace(pbContent)) sb.AppendLine(pbContent);
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                var col = _table.Columns[i];
                if (!col.ColumnPrimaryKey)
                {
                    var colType = col.ColumnType;
                    switch (col.ColumnType)
                    {
                        case "varchar":
                            if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength})";
                            break;
                        case "decimal":
                            if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength},{col.ColumnTypeFloat})";
                            break;
                    }
                    sb.AppendLine($"    -- {col.ColumnText}");
                    sb.Append($"    \"{col.ColumnDbName}\" {colType} {(col.ColumnNullable ? "NULL" : "NOT NULL")}");
                    if (!string.IsNullOrWhiteSpace(tabPrimaryKey) || (string.IsNullOrWhiteSpace(tabPrimaryKey) && i < _table.Columns.Count - 1)) sb.Append(',');
                    sb.AppendLine();
                }
            }
            if (!string.IsNullOrWhiteSpace(tabPrimaryKey)) sb.AppendLine($"    CONSTRAINT \"PK_{tabName}\" PRIMARY KEY ({tabPrimaryKey})");
            sb.AppendLine($");");
            sb.AppendLine();
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                var col = _table.Columns[i];
                var colType = col.ColumnType;
                switch (col.ColumnType)
                {
                    case "varchar":
                        if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength})";
                        break;
                    case "decimal":
                        if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength},{col.ColumnTypeFloat})";
                        break;
                }
                sb.AppendLine($"-- 在 {tabText} 表中添加 {col.ColumnText} 字段");
                sb.AppendLine($"alter table {tabFullName} add \"{col.ColumnDbName}\" {colType} {(col.ColumnNullable ? "NULL" : "NOT NULL")};");
                sb.AppendLine($"-- 更新 {tabText} 表中的 {col.ColumnText} 字段");
                sb.AppendLine($"alter table {tabFullName} alter column \"{col.ColumnDbName}\" type {colType} using {GetUnderScoreCase(col.ColumnName)}::{colType};");
                sb.AppendLine($"-- 在 {tabText} 表中添加 {col.ColumnText} 字段描述");
                sb.AppendLine($"COMMENT ON COLUMN {tabFullName}.{col.ColumnDbName} IS '{col.ColumnText}';");
                sb.AppendLine();
            }
            SetStatus("生成Sql成功");
            using (SaveFileDialog f = new SaveFileDialog())
            {
                f.FileName = $"{tabName}.sql";
                f.Filter = "Sql文件(*.sql)|*.sql";
                if (f.ShowDialog() == DialogResult.OK)
                {
                    byte[] bytes = Encoding.UTF8.GetBytes(sb.ToString());
                    using (var fs = System.IO.File.Open(f.FileName, System.IO.FileMode.Create, System.IO.FileAccess.Write))
                    {
                        fs.Position = 0;
                        fs.Write(bytes, 0, bytes.Length);
                    }
                    SetStatus("导出成功");
                }
            }
        }

        private void toolCfgSetting_Click(object sender, EventArgs e)
        {
            Process.Start($"{_localPath}config\\setting.json");
        }

        private void toolCfgData_Click(object sender, EventArgs e)
        {
            Process.Start($"{_localPath}config\\data.json");
        }

        private void toolCfgSql_Click(object sender, EventArgs e)
        {
            string path = $"{_localConfigPath}sql_pb.txt";
            if (!System.IO.File.Exists(path)) using (var f = System.IO.File.Create(path)) { };
            Process.Start(path);
        }

        private void toolMakeCSharpSql_Click(object sender, EventArgs e)
        {
            // 填充对象
            FillGirdToTable();
            StringBuilder sb = new StringBuilder();
            string tabAbbr = "";
            if (_table.Properties.ContainsKey("Abbr")) tabAbbr = _table.Properties["Abbr"];
            string tabSchema = "";
            if (_table.Properties.ContainsKey("Schema")) tabSchema = _table.Properties["Schema"];
            string tabInherit = "";
            if (_table.Properties.ContainsKey("Inherit")) tabInherit = ": " + _table.Properties["Inherit"];
            string tabName = "";
            if (_table.Properties.ContainsKey("Name")) tabName = _table.Properties["Name"];
            string tabText = "";
            if (_table.Properties.ContainsKey("Text")) tabText = _table.Properties["Text"];
            string tabFullName = (string.IsNullOrWhiteSpace(tabSchema) ? "" : tabSchema + ".") + GetUnderScoreCase(tabName);
            sb.AppendLine("$@\"select");
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                var col = _table.Columns[i];
                sb.Append($"{tabAbbr}.{GetUnderScoreCase(col.ColumnName)} as {col.ColumnName}");
                if (i < _table.Columns.Count - 1) sb.Append(",");
                sb.AppendLine();
            }
            sb.AppendLine($"from {tabFullName} {tabAbbr}");
            sb.AppendLine($"where not {tabAbbr}.is_deleted\"");
            FrmText frm = new FrmText();
            frm.Text = $"代码生成 - C#原生查询代码 - [{tabText}({tabName})]";
            frm.ContentTextBox.Text = sb.ToString();
            frm.Show();
        }

        private void toolImportEntity_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrWhiteSpace(_path))
            {
                MessageBox.Show("请在新界面执行导入");
                return;
            }
            using (FrmImport frm = new FrmImport())
            {
                if (frm.ShowDialog() == DialogResult.OK)
                {
                    _table = frm.Table;
                    ShowTables();
                    ShowColumns();
                }
            }
        }

        private void toolTransUCase_Click(object sender, EventArgs e)
        {
            // 填充对象
            FillGirdToTable();
            _table.Properties["DbName"] = GetUnderScoreCase(_table.Properties["Name"]);
            _table.Properties["Abbr"] = GetAbbr(_table.Properties["Name"]);
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                _table.Columns[i].ColumnDbName = GetUnderScoreCase(_table.Columns[i].ColumnName);
            }
            ShowColumns();
            ShowTables();
        }

        private void 新建NToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(_path)) return;
            // 启动一个新程序来运行
            ProcessStartInfo info = new ProcessStartInfo();
            info.FileName = _exePath;
            info.UseShellExecute = true;
            info.CreateNoWindow = false;
            var pro = Process.Start(info);
        }

        private void toolMakeCSharpDbset_Click(object sender, EventArgs e)
        {
            // 填充对象
            FillGirdToTable();
            StringBuilder sb = new StringBuilder();
            string tabSchema = "";
            if (_table.Properties.ContainsKey("Schema")) tabSchema = _table.Properties["Schema"];
            string tabInherit = "";
            if (_table.Properties.ContainsKey("Inherit")) tabInherit = ": " + _table.Properties["Inherit"];
            string tabName = "";
            if (_table.Properties.ContainsKey("Name")) tabName = _table.Properties["Name"];
            string tabDbName = "";
            if (_table.Properties.ContainsKey("DbName")) tabDbName = _table.Properties["DbName"];
            string tabText = "";
            if (_table.Properties.ContainsKey("Text")) tabText = _table.Properties["Text"];
            sb.AppendLine($"/// <summary>");
            sb.AppendLine($"/// {tabText}");
            sb.AppendLine($"/// </summary>");
            sb.AppendLine($"public virtual DbSet<{tabName}> {tabName}s {{ get; set; }}");
            FrmText frm = new FrmText();
            frm.Text = $"DbSet代码生成 - C#类 - [{tabText}({tabName})]";
            frm.ContentTextBox.Text = sb.ToString();
            frm.Show();
        }

        private void toolMakeNpgsColumn_Click(object sender, EventArgs e)
        {
            var view = this.dataGridView1;
            if (view.SelectedRows.Count <= 0) { MessageBox.Show("请先选择一条"); return; }
            int rowIndex = view.SelectedRows[0].Index;
            string name = (string)view.Rows[rowIndex].Cells["ColumnName"].Value;
            // 填充对象
            FillGirdToTable();
            StringBuilder sb = new StringBuilder();
            string tabSchema = "";
            if (_table.Properties.ContainsKey("Schema")) tabSchema = _table.Properties["Schema"];
            string tabInherit = "";
            if (_table.Properties.ContainsKey("Inherit")) tabInherit = ": " + _table.Properties["Inherit"];
            string tabName = "";
            if (_table.Properties.ContainsKey("Name")) tabName = _table.Properties["DbName"];
            string tabText = "";
            if (_table.Properties.ContainsKey("Text")) tabText = _table.Properties["Text"];
            string tabFullName = (string.IsNullOrWhiteSpace(tabSchema) ? "" : tabSchema + ".") + tabName;

            var col = _table.Columns.Where(d => d.ColumnName == name).FirstOrDefault();
            if (col is null) { MessageBox.Show($"字段'{name}'不存在"); return; }
            string colDefaultValue = "''";
            //for (int i = 0; i < _table.Columns.Count; i++)
            //{
            //    var col = _table.Columns[i];
            var colType = col.ColumnType;
            switch (col.ColumnType)
            {
                case "varchar":
                    if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength})";
                    break;
                case "decimal":
                    if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength},{col.ColumnTypeFloat})";
                    colDefaultValue = "0";
                    break;
                case "integer":
                    colDefaultValue = "0";
                    break;
                case "bool":
                    colDefaultValue = "false";
                    break;
            }
            
            if (col.ColumnNullable)
            {
                sb.AppendLine($"-- 在 {tabText} 表中添加 {col.ColumnText} 可空字段");
                sb.AppendLine($"alter table {tabFullName} add \"{col.ColumnDbName}\" {colType} NULL;");
                sb.AppendLine($"-- 设置 {tabText} 表的 {col.ColumnText} 字段描述");
                sb.AppendLine($"COMMENT ON COLUMN {tabFullName}.{col.ColumnDbName} IS '{col.ColumnText}';");
                sb.AppendLine();
                sb.AppendLine($"-- 设置 {tabText} 表中的 {col.ColumnText} 字段可为空");
                sb.AppendLine($"alter table {tabFullName} alter column \"{col.ColumnDbName}\" drop NOT NULL;");
                sb.AppendLine();
            }
            else
            {
                sb.AppendLine($"-- 直接添加非空字段（无数据）");
                sb.AppendLine();
                sb.AppendLine($"-- 在 {tabText} 表中添加 {col.ColumnText} 非空字段");
                sb.AppendLine($"alter table {tabFullName} add \"{col.ColumnDbName}\" {colType} NOT NULL;");
                sb.AppendLine($"-- 设置 {tabText} 表的 {col.ColumnText} 字段描述");
                sb.AppendLine($"COMMENT ON COLUMN {tabFullName}.{col.ColumnDbName} IS '{col.ColumnText}';");
                sb.AppendLine();
                sb.AppendLine($"-- 添加可空字段后转非空（有数据）");
                sb.AppendLine();
                sb.AppendLine($"-- 在 {tabText} 表中添加 {col.ColumnText} 可空字段");
                sb.AppendLine($"alter table {tabFullName} add \"{col.ColumnDbName}\" {colType} NULL;");
                sb.AppendLine($"-- 设置 {tabText} 表的 {col.ColumnText} 字段描述");
                sb.AppendLine($"COMMENT ON COLUMN {tabFullName}.{col.ColumnDbName} IS '{col.ColumnText}';");
                sb.AppendLine($"-- 设置 {tabText} 表中的 {col.ColumnText} 字段原有为空的字段给初始值");
                sb.AppendLine($"update {tabFullName} set \"{col.ColumnDbName}\" = {colDefaultValue} where \"{col.ColumnDbName}\" is NULL;");
                sb.AppendLine($"-- 设置 {tabText} 表中的 {col.ColumnText} 字段不可为空");
                sb.AppendLine($"alter table {tabFullName} alter column \"{col.ColumnDbName}\" set NOT NULL;");
                sb.AppendLine();
            }
            sb.AppendLine($"-- 更新 {tabText} 表中的 {col.ColumnText} 字段类型");
            sb.AppendLine($"alter table {tabFullName} alter column \"{col.ColumnDbName}\" type {colType} using {GetUnderScoreCase(col.ColumnName)}::{colType};");
            sb.AppendLine();
            if (col.ColumnIndexer)
            {
                if (col.ColumnUnique)
                {
                    sb.AppendLine($"-- 设置 {tabText} 表的 {col.ColumnText} 为唯一索引字段");
                    sb.AppendLine($"CREATE UNIQUE INDEX {tabName}_{col.ColumnDbName}_idx ON {tabFullName} USING btree ({col.ColumnDbName});");
                }
                else
                {
                    sb.AppendLine($"-- 设置 {tabText} 表的 {col.ColumnText} 为索引字段");
                    sb.AppendLine($"CREATE INDEX {tabName}_{col.ColumnDbName}_idx ON {tabFullName} ({col.ColumnDbName});");
                }
            }
            //}
            FrmText frm = new FrmText();
            frm.Text = $"Sql生成 - 表更更新 - [{tabText}({tabName})]";
            frm.ContentTextBox.Text = sb.ToString();
            frm.Show();
        }

        private void toolMakeNpgsTable_Click(object sender, EventArgs e)
        {
            // 读取预生成内容
            string path = $"{_localConfigPath}sql_pb.txt";
            string pbContent = "";
            if (!System.IO.File.Exists(path)) using (var f = System.IO.File.Create(path)) { };
            using (var f = System.IO.File.Open(path, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                byte[] bytes = new byte[f.Length];
                f.Position = 0;
                f.Read(bytes, 0, bytes.Length);
                pbContent = System.Text.Encoding.UTF8.GetString(bytes);
            }
            // 填充对象
            FillGirdToTable();
            StringBuilder sb = new StringBuilder();
            string tabSchema = "";
            if (_table.Properties.ContainsKey("Schema")) tabSchema = _table.Properties["Schema"];
            string tabInherit = "";
            if (_table.Properties.ContainsKey("Inherit")) tabInherit = ": " + _table.Properties["Inherit"];
            string tabName = "";
            if (_table.Properties.ContainsKey("Name")) tabName = _table.Properties["DbName"];
            string tabText = "";
            if (_table.Properties.ContainsKey("Text")) tabText = _table.Properties["Text"];
            string tabFullName = (string.IsNullOrWhiteSpace(tabSchema) ? "" : tabSchema + ".") + tabName;
            string tabPrimaryKey = "";
            sb.AppendLine($"-- 添加{tabText}表");
            sb.AppendLine($"CREATE TABLE {tabFullName}(");
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                var col = _table.Columns[i];
                if (col.ColumnPrimaryKey)
                {
                    var colType = col.ColumnType;
                    switch (col.ColumnType)
                    {
                        case "varchar":
                            if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength})";
                            break;
                        case "decimal":
                            if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength},{col.ColumnTypeFloat})";
                            break;
                    }
                    //sb.AppendLine($"    -- {col.ColumnText}");
                    sb.AppendLine($"    \"{col.ColumnDbName}\" {colType} {(col.ColumnNullable ? "NULL" : "NOT NULL")},");
                    tabPrimaryKey = GetUnderScoreCase(col.ColumnName);
                }
            }
            if (!string.IsNullOrWhiteSpace(pbContent)) sb.AppendLine(pbContent);
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                var col = _table.Columns[i];
                if (col.ColumnMake)
                {
                    if (!col.ColumnPrimaryKey)
                    {
                        var colType = col.ColumnType;
                        switch (col.ColumnType)
                        {
                            case "varchar":
                                if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength})";
                                break;
                            case "decimal":
                                if (col.ColumnTypeLength > 0) colType += $"({col.ColumnTypeLength},{col.ColumnTypeFloat})";
                                break;
                        }
                        //sb.AppendLine($"    -- {col.ColumnText}");
                        sb.Append($"    \"{col.ColumnDbName}\" {colType} {(col.ColumnNullable ? "NULL" : "NOT NULL")}");
                        if (!string.IsNullOrWhiteSpace(tabPrimaryKey) || (string.IsNullOrWhiteSpace(tabPrimaryKey) && i < _table.Columns.Count - 1)) sb.Append(',');
                        sb.AppendLine();
                    }
                }
            }
            if (!string.IsNullOrWhiteSpace(tabPrimaryKey)) sb.AppendLine($"    CONSTRAINT \"PK_{tabName}\" PRIMARY KEY ({tabPrimaryKey})");
            sb.AppendLine($");");
            sb.AppendLine();
            // 生成描述
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                var col = _table.Columns[i];
                if (col.ColumnMake)
                {
                    sb.AppendLine($"COMMENT ON COLUMN {tabFullName}.{col.ColumnDbName} IS '{col.ColumnText}';");
                }
            }
            sb.AppendLine();
            // 生成索引
            for (int i = 0; i < _table.Columns.Count; i++)
            {
                var col = _table.Columns[i];
                if (col.ColumnIndexer)
                {
                    if (col.ColumnUnique)
                    {
                        sb.AppendLine($"CREATE UNIQUE INDEX {tabName}_{col.ColumnDbName}_idx ON {tabFullName} USING btree ({col.ColumnDbName});");
                    }
                    else
                    {
                        sb.AppendLine($"CREATE INDEX {tabName}_{col.ColumnDbName}_idx ON {tabFullName} ({col.ColumnDbName});");
                    }
                }
            }
            FrmText frm = new FrmText();
            frm.Text = $"Sql生成 - 表创建 - [{tabText}({tabName})]";
            frm.ContentTextBox.Text = sb.ToString();
            frm.Show();
        }
    }
}
